﻿using System;
using System.Data;
using System.Windows.Forms;
using System.Xml;
using System.IO;
using System.Text.RegularExpressions;

namespace ClearProjectImage
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// 项目文件路径
        /// </summary>
        private string projectFilePath = string.Empty;

        /// <summary>
        /// 项目根目录
        /// </summary>
        private string projectPath = string.Empty;

        /// <summary>
        /// 项目命名空间
        /// </summary>
        private string rootNamespace = string.Empty;

        /// <summary>
        /// 搜索关键字
        /// </summary>
        private string keyWord = string.Empty;

        public Form1()
        {
            InitializeComponent();
        }

        #region 方法
        /// <summary>
        /// 加载所有资源图片
        /// </summary>
        /// <param name="iFilePath"></param>
        private void LoadAllResList(string iFilePath)
        {
            DataSet ds = new DataSet();
            ds.ReadXml(iFilePath);
            if (ds.Tables.Count > 0)
            {
                try
                {
                    DataTable dtAllRes = ds.Tables["data"];
                    this.lvAllRes.Items.Clear();
                    for (int i = 0; i < dtAllRes.Rows.Count; i++)
                    {
                        string[] item = new string[] { dtAllRes.Rows[i]["name"].ToString().Replace("-", "_"), dtAllRes.Rows[i]["value"].ToString().Split(new char[] { ';' })[0] };
                        this.lvAllRes.Items.Add(new ListViewItem(item));
                        this.gBoxAllRes.Text = "所有资源图片(" + this.lvAllRes.Items.Count.ToString() + "个)";
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("读取资源文件失败！/n错误原因:" + ex.Message.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                MessageBox.Show("文件格式错误！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private XmlElement GetXmlNode(XmlElement iNode, string iName)
        {
            XmlElement xmlNode = null;
            for (int i = 0; i < iNode.ChildNodes.Count; i++)
            {
                if (iNode.ChildNodes[i].Name == iName)
                {
                    xmlNode = (XmlElement)iNode.ChildNodes[i];
                    break;
                }
            }

            return xmlNode;
        }

        /// <summary>
        /// 通过项目文件分析项目中包含的CS文件
        /// </summary>
        /// <param name="iProjectFilePath"></param>
        private void AnalyzeDirectory(string iProjectFilePath)
        {
            if (File.Exists(iProjectFilePath))
            {
                DataSet ds = new DataSet();
                ds.ReadXml(iProjectFilePath);
                if (ds.Tables.Count > 0)
                {
                    DataTable dtCsFile = ds.Tables["Compile"];
                    for (int m = 0; m < dtCsFile.Rows.Count; m++)
                    {
                        //查找文件中使用资源的地方
                        if (File.Exists(this.projectPath + "\\" + dtCsFile.Rows[m]["Include"].ToString()))
                        {
                            this.AnalyzeFile(this.projectPath + "\\" + dtCsFile.Rows[m]["Include"].ToString());
                        }
                    }

                    this.LoadNoUsedRes();
                }
                else
                {
                    MessageBox.Show("文件格式错误！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        /// <summary>
        /// 查找文件中使用资源的地方
        /// </summary>
        /// <param name="iFilePath"></param>
        private void AnalyzeFile(string iFilePath)
        {
            using (FileStream fStream = File.Open(iFilePath, FileMode.OpenOrCreate))
            {
                byte[] b = new byte[fStream.Length];
                fStream.Read(b, 0, b.Length);

                string s = System.Text.ASCIIEncoding.UTF8.GetString(b);
                Regex re = new Regex(this.keyWord + "(?<res>[^;:\"].+?)(;|:| |,)");
                MatchCollection list = re.Matches(s);

                foreach (Match m in list)
                {
                    string subString = m.Groups["res"].Value;
                    if (!this.IsExsits(subString))
                    {
                        string[] item = new string[] { subString.Replace("-", "_"), iFilePath };
                        this.lvUsedRes.Items.Add(new ListViewItem(item));
                        this.gBoxUsedRes.Text = "用到的资源图片(" + this.lvUsedRes.Items.Count.ToString() + "个)";
                    }
                }
            }
        }

        /// <summary>
        /// 加载未使用的资源
        /// </summary>
        private void LoadNoUsedRes()
        {
            this.lvNoUsedRes.Items.Clear();
            for (int i = 0; i < this.lvAllRes.Items.Count; i++)
            {
                bool flag = true;
                for (int m = 0; m < this.lvUsedRes.Items.Count; m++)
                {
                    //如果this.lvAllRes.Items[i].SubItems[0].Text已经包含在this.lvUsedRes中，则跳出循环；否则将其添加到未使用列表中
                    if (this.lvAllRes.Items[i].SubItems[0].Text.Trim() == this.lvUsedRes.Items[m].SubItems[0].Text.Trim() || "_" + this.lvAllRes.Items[i].SubItems[0].Text.Trim() == this.lvUsedRes.Items[m].SubItems[0].Text.Trim())
                    {
                        flag = false;
                        break;
                    }
                }

                if (flag)
                {
                    string[] item = new string[] { this.lvAllRes.Items[i].SubItems[0].Text, this.lvAllRes.Items[i].SubItems[1].Text };
                    this.lvNoUsedRes.Items.Add(new ListViewItem(item));
                    this.gBoxNoUsedRes.Text = "未用到的资源图片(" + this.lvNoUsedRes.Items.Count.ToString() + "个)";
                }
            }
        }

        /// <summary>
        /// 用到的资源列表中是否已存在该资源
        /// </summary>
        /// <param name="iName"></param>
        /// <returns></returns>
        private bool IsExsits(string iName)
        {
            bool flag = false;
            for (int i = 0; i < this.lvUsedRes.Items.Count; i++)
            {
                if (this.lvUsedRes.Items[i].SubItems[0].Text == iName)
                {
                    flag = true;
                    break;
                }
            }

            return flag;
        }

        /// <summary>
        /// 移除未使用的资源文件
        /// </summary>
        private void MoveFile()
        {
            string newResDir = "e:\\res";
            if (!Directory.Exists(newResDir))
            {
                Directory.CreateDirectory(newResDir);
            }

            for (int i = 0; i < this.lvNoUsedRes.Items.Count; i++)
            {
                string fileName = this.lvNoUsedRes.Items[i].SubItems[1].Text.Substring(this.lvNoUsedRes.Items[i].SubItems[1].Text.LastIndexOf("\\"));
                string filePath = this.projectPath + "\\Resources" + fileName;
                if (File.Exists(filePath))
                {
                    File.Move(filePath, newResDir + fileName);
                }
            }
        }

        /// <summary>
        /// 修改Resources.resx文件
        /// </summary>
        private void UpdateResxFile()
        {
            string resFilePath = projectPath + "\\Properties\\Resources.resx"; //项目资源文件路径
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(resFilePath);
            XmlNodeList xnl = xmlDoc.SelectSingleNode("root").ChildNodes;
            for (int i = 0; i < this.lvNoUsedRes.Items.Count; i++)
            {
                foreach (XmlNode xn in xnl)
                {
                    XmlElement xe = xn as XmlElement;
                    if (xe != null)
                    {
                        if (xe.GetAttribute("name").Replace("-", "_") == this.lvNoUsedRes.Items[i].SubItems[0].Text)
                        {
                            //删除该节点的全部内容
                            xe.ParentNode.RemoveChild(xe);
                            break;
                        }
                    }
                }
            }

            xmlDoc.Save(resFilePath); //保存到XML文档
        }

        /// <summary>
        /// 修改Resources.Designer.cs文件
        /// </summary>
        private void UpdateDesignerFile()
        {
            string sContent = string.Empty;
            string resFilePath = projectPath + "\\Properties\\Resources.Designer.cs"; //项目资源文件路径
            using (StreamReader objReader = new StreamReader(resFilePath))
            {
                sContent = objReader.ReadToEnd();
                for (int i = 0; i < this.lvNoUsedRes.Items.Count; i++)
                {
                    string s = "        \\r\\n( *)internal static System.Drawing.Bitmap " + this.lvNoUsedRes.Items[i].SubItems[0].Text + " \\{(.[^}]*)}\r\n( +)}\r\n";
                    Regex re = new Regex(s);
                    if (re.Matches(sContent).Count == 0)
                    {
                        s = "        \\r\\n( *)internal static System.Drawing.Bitmap _" + this.lvNoUsedRes.Items[i].SubItems[0].Text + " \\{(.[^}]*)}\r\n( +)}\r\n";
                        re = new Regex(s);
                    }

                    sContent = re.Replace(sContent, "");
                }
            }

            using (StreamWriter objWriter = new StreamWriter(resFilePath))
            {
                objWriter.Write(sContent);
            }
        }
        #endregion

        #region 文件菜单
        /// <summary>
        /// 打开资源文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 打开ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFlg = new OpenFileDialog();
            openFlg.Filter = @"项目文件(.csproj)|*.csproj";
            if (openFlg.ShowDialog() == DialogResult.OK)
            {
                this.projectFilePath = openFlg.FileName; //项目文件路径
                this.projectPath = projectFilePath.Substring(0, projectFilePath.LastIndexOf("\\"));

                XmlDocument xmlDoc = new XmlDocument();
                XmlElement node = null;
                xmlDoc.Load(this.projectFilePath);
                node = this.GetXmlNode(xmlDoc.DocumentElement, "PropertyGroup");
                this.rootNamespace = this.GetXmlNode(node, "RootNamespace").InnerText;
                this.keyWord = this.rootNamespace + "\\.Properties.Resources\\.";

                string resFilePath = projectPath + "\\Properties\\Resources.resx"; //项目资源文件路径
                if (File.Exists(resFilePath))
                {
                    this.LoadAllResList(resFilePath);
                }
                else
                {
                    MessageBox.Show("找不到资源文件Resources.resx！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }
        #endregion

        #region 操作菜单
        /// <summary>
        /// 查找未用到的资源
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 分析ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.lvUsedRes.Items.Clear();
            this.AnalyzeDirectory(this.projectFilePath);
        }

        /// <summary>
        /// 移除未用到的资源
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 移除未用到的资源图片ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.UpdateDesignerFile();
            this.UpdateResxFile();
            this.MoveFile();
            MessageBox.Show("移除成功！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        #endregion

    }
}
